﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Celeriq.Client.Interfaces;
using Celeriq.Common;

namespace Celeriq.RepositoryAPI.Test
{
    internal class Program
    {
        private const string MACHINE = "localhost";

        private static void Main(string[] args)
        {
            #region Credentials

            var credentials = new UserCredentials();
            using (var factory = SystemCoreInteractDomain.GetFactory(MACHINE))
            {
                var server = factory.CreateChannel();
                credentials.UserName = "root";
                credentials.Password = "password";
                credentials.Password = Celeriq.Utilities.SecurityHelper.Encrypt(server.GetPublicKey(), credentials.Password);
            }

            #endregion

            //CreateManyRepository(credentials);
            //IterateRepository(credentials);
            //CreateAndLoadItems(credentials);
            ClearRepository(credentials);

            Console.WriteLine("Press any key...");
            Console.ReadLine();

        }

        private static void ClearRepository(UserCredentials credentials)
        {
            Guid repositoryId = Guid.Empty;
            using (var factory = SystemCoreInteractDomain.GetFactory(MACHINE))
            {
                var server = factory.CreateChannel();
                var repositoryList = server.GetRepositoryPropertyList(credentials, 1, 1);
                if (repositoryList.Count > 0)
                {
                    repositoryId = repositoryList.First().Repository.ID;
                }
            }

            if (repositoryId != Guid.Empty)
            {
                using (var factory = RepositoryConnection.GetFactory(MACHINE, repositoryId.ToString()))
                {
                    var service = factory.CreateChannel();
                    RepositoryConnection.Clear(service, credentials);
                }
            }

        }

        //private static void CreateAndLoadItems(UserCredentials credentials)
        //{
        //    //Load Test
        //    #region Create repository if not exists

        //    var item = new BaseRemotingObject();
        //    item.Repository = new Celeriq.Common.RepositoryDefinition();
        //    item.Repository.LoadXml(GetRepositoryTemplate());
        //    item.Repository.ID = new Guid("22999192-A01F-4E48-8922-50AD48332736");
        //    item.Repository.Name = "LoadTest-Iterate";
        //    using (var factory = SystemCoreInteractDomain.GetFactory(MACHINE))
        //    {
        //        var server = factory.CreateChannel();
        //        if (!server.RepositoryExists(item.Repository.ID, credentials))
        //        {
        //            Console.WriteLine("Create Repository: " + item.Repository.Name);
        //            server.SaveRepository(item.Repository, credentials);
        //        }
        //        else
        //        {
        //            Console.WriteLine("Repository Exists: " + item.Repository.Name);
        //            server.DataLoadRepository(item.Repository.ID, credentials);
        //        }

        //        //Now load data multiple times
        //        const int LoadIterations = 1000;
        //        for (var ii = 0; ii < LoadIterations; ii++)
        //        {
        //            LoadRepository(item.Repository.ID, credentials);
        //        }
        //        server.Compress(item.Repository.ID, credentials);
        //    }

        //    #endregion

        //}

        private static void IterateRepository(UserCredentials credentials)
        {
            //Load Test
            #region Create repository if not exists

            var item = new BaseRemotingObject();
            item.Repository = new Celeriq.Common.RepositoryDefinition();
            item.Repository.LoadXml(GetRepositoryTemplate());
            item.Repository.ID = new Guid("44999192-A01F-4E48-8922-50AD48332736");
            item.Repository.Name = "LoadTest-Iterate";
            using (var factory = SystemCoreInteractDomain.GetFactory(MACHINE))
            {
                var server = factory.CreateChannel();
                if (!server.RepositoryExists(item.Repository.ID, credentials))
                {
                    Console.WriteLine("Create Repository: " + item.Repository.Name);
                    server.SaveRepository(item.Repository, credentials);
                }
                else
                {
                    Console.WriteLine("Repository Exists: " + item.Repository.Name);
                    server.DataLoadRepository(item.Repository.ID, credentials);
                }

                //Now load data multiple times
                const int LoadIterations = 100;
                for (var ii = 0; ii < LoadIterations; ii++)
                {
                    LoadRepository(item.Repository.ID, credentials);
                }
                server.Compress(item.Repository.ID, credentials);
            }

            #endregion
        }

        private static void CreateManyRepository(UserCredentials credentials)
        {
            //Load Test
            const int TOTALREPOSITORY = 50;
            var baseName = "LoadTest-";
            for (var ii = 0; ii < TOTALREPOSITORY; ii++)
            {
                var repositoryName = "LoadTest-" + ii.ToString("000");

                #region Create repository if not exists

                var item = new BaseRemotingObject();
                item.Repository = new Celeriq.Common.RepositoryDefinition();
                item.Repository.LoadXml(GetRepositoryTemplate());
                item.Repository.ID = new Guid("F3999192-A01F-4E48-8922-50AD48" + ii.ToString("000000"));
                item.Repository.Name = repositoryName;
                using (var factory = SystemCoreInteractDomain.GetFactory(MACHINE))
                {
                    var server = factory.CreateChannel();
                    if (!server.RepositoryExists(item.Repository.ID, credentials))
                    {
                        Console.WriteLine("Create Repository: " + item.Repository.Name);
                        server.SaveRepository(item.Repository, credentials);
                        //server.StartRepository(new Guid(RepositoryConnection.WCFKey), credentials);
                        LoadRepository(item.Repository.ID, credentials);
                        Console.WriteLine("Loaded Repository: " + item.Repository.Name);
                    }
                    else
                    {
                        Console.WriteLine("Repository Exists: " + item.Repository.Name);
                        //server.StartRepository(new Guid(RepositoryConnection.WCFKey), credentials);
                    }
                    server.DataLoadRepository(item.Repository.ID, credentials);
                }

                #endregion
            }
        }

        private static string GetRepositoryTemplate()
        {
            var a = Assembly.GetExecutingAssembly();
            var st = a.GetManifestResourceStream("Celeriq.RepositoryAPI.Test.LoadTest.celeriq");
            var sr = new StreamReader(st);
            return sr.ReadToEnd();
        }

        private static string[] _Dim1Array = {"AAA", "BBB", "CCC", "DDD", "EEE", "FFF"};
        private static string[] _Dim2Array = {"ZZZ", "XXX", "YYY", "WWW"};

        private static void LoadRepository(Guid repositoryId, UserCredentials credentials)
        {
            const int LOOPS = 500;
            var rnd = new Random(0);
            var list = new List<ListingItem>();
            for (var ii = 0; ii < LOOPS; ii++)
            {
                var item = new ListingItem();
                item.ID = ii;
                item.Make = _Dim1Array[rnd.Next(0, _Dim1Array.Length)];
                item.Model = _Dim2Array[rnd.Next(0, _Dim2Array.Length)];
                list.Add(item);
            }

            using (var factory = RepositoryConnection.GetFactory(MACHINE, repositoryId.ToString()))
            {
                var service = factory.CreateChannel();
                RepositoryConnection.UpdateData(list, credentials, service);
            }

        }
    }
}